package com.myorigin.weblog.jwt.service;

import com.myorigin.weblog.common.domain.dos.UserDO;
import com.myorigin.weblog.common.domain.dos.UserRoleDO;
import com.myorigin.weblog.common.domain.mapper.UserMapper;
import com.myorigin.weblog.common.domain.mapper.UserRoleMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 获取用户细节进行登录验证
 */
@Service
@Slf4j
public class UserDetailServiceImpl implements UserDetailsService {//UserDetailsService 是 Spring Security 提供的接口
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //从数据库中查询用户
        UserDO userDO = userMapper.findByUsername(username);

        //判断用户是否存在
        if(Objects.isNull(userDO)){
            throw new UsernameNotFoundException("该用户不存在");
        }

        //(密文在PasswordEncoderConfig类中生成)
        //authoritie 用于指定角色，这里不再写死为 ADMIN 管理员
        // 用户角色
        List<UserRoleDO> roleDOS = userRoleMapper.selectByUsername(username);

        String[] roleArr = null;
        //转数组
        if(!CollectionUtils.isEmpty(roleDOS)){
            List<String> roles = roleDOS.stream().map(UserRoleDO::getRole).collect(Collectors.toList());
            roleArr = roles.toArray(new String[roles.size()]);
        }

        // authorities 用于指定用户的角色
        // 这里的 authorities 角色字段，我们不再写死，而是改从数据库中查询，当角色不为空时，将其转换为数组，并传入到 authorities 字段中。
        return User.withUsername(userDO.getUsername())
                .password(userDO.getPassword())
                .authorities(roleArr)
                .build();
    }
}
